﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WMM.Tapioca;
using TapiocaWpf.Utilities;
using System.Threading;
using System.Resources;
using WMM.Tapioca.Utilities;
using System.Diagnostics;
using Microsoft.Win32;
using System.Net;
using System.ComponentModel;
using WMM.Tapioca.Instance;
using WMM.Tapioca.Validate;
using WMM.Tapioca.Taxonomy;
using WMM.Tapioca.Linkbase;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using WMM.Tapioca.Formula;
using WMM.Tapioca.Formula.Filters;
using WMM.Tapioca.XbrlDimension;
using System.Data;
using System.Globalization;
using TapiocaWpf.Model;
using System.IO;
using System.Windows.Threading;
using TapiocaWpf.Controls;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit;
using TapiocaWpf.Rendering;

namespace TapiocaWpf.Views
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IView
    {
        string fileName;
        static string pathToDotFile;
        string diagramFile;

        TreeView treeViewDts;
        TreeView tvPresentation;
        TreeView tvDefinition;
        TreeView tvCalculation;
        TreeView tvDimension;
        TreeView tvFormula;
        TreeView tvGeneric;

        XbrlDocument xbrlDoc; 

        ProgressWindow progressWindow = new ProgressWindow();
        UserSettings userSettings = new UserSettings();
        internal TextEditor textEditor;

        private static Action EmptyDelegate = delegate() { };

        public MainWindow()
        {
            //Get the Default installed culture    
            Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InstalledUICulture;

            Application.Current.MainWindow = this;

            InitializeComponent();

            InitializeBackgroundWorkers();

            CreateRecentFileMenuItem();

            AddHotKeys();

            userSettings.LayoutEngine = "dot";
            userSettings.FileType = "png";
            userSettings.Save();  
        }        


        # region Initialization

        BackgroundWorker backgroundWorkerOpenFile = new BackgroundWorker();
        BackgroundWorker backgroundWorkerValidateDTS = new BackgroundWorker();
        BackgroundWorker backgroundWorkerGenDiagram = new BackgroundWorker();
        BackgroundWorker backgroundWorkerFormula = new BackgroundWorker();
        BackgroundWorker backgroundWorkerCalculation = new BackgroundWorker();

        private void InitializeBackgroundWorkers()
        {
            // backgroundWorker
            // 
            this.backgroundWorkerGenDiagram.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorkerGenDiagram_DoWork);
            this.backgroundWorkerGenDiagram.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorkerGenDiagram_RunWorkerCompleted);
            //             
            // backgroundWorkerFormula
            // 
            this.backgroundWorkerFormula.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorkerFormula_DoWork);
            this.backgroundWorkerFormula.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorkerFormula_RunWorkerCompleted);
            // 
            // backgroundWorkerCalculation
            // 
            this.backgroundWorkerCalculation.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorkerCalculation_DoWork);
            this.backgroundWorkerCalculation.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorkerCalculation_RunWorkerCompleted);
            // 
            // backgroundWorkerOpenFile
            // 
            this.backgroundWorkerOpenFile.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorkerOpenFile_DoWork);
            this.backgroundWorkerOpenFile.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorkerOpenFile_RunWorkerCompleted);
            // 
            // backgroundWorkerValidateDTS
            // 
            this.backgroundWorkerValidateDTS.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorkerValidateDTS_DoWork);
            this.backgroundWorkerValidateDTS.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorkerValidateDTS_RunWorkerCompleted);
        }


        private void CreateRecentFileMenuItem()
        {
            List<string> recentFilesOld = userSettings.RecentlyOpenedFiles;

            if (recentFilesOld == null)
            {
                recentFilesOld = new List<string>();
            }

            int k = 1;
            foreach (string recentFile in recentFilesOld)
            {
                MenuItem recentFileMenuItem = new MenuItem();
                recentFileMenuItem.Name = "recentFile" + k + "ToolStripMenuItem";
                recentFileMenuItem.Header = recentFile;
                recentFileMenuItem.Click += new RoutedEventHandler(recentFile1MenuItem_Click);
                this.recentFilesMenuItem.Items.Add(recentFileMenuItem);
                k = k + 1;
            }
        }


        private void InitializeViews()
        {
            ResourceManager LocRM = new ResourceManager("Tapioca.Views.MainForm", System.Reflection.Assembly.GetExecutingAssembly());

        }

        #endregion


        #region MVC pattern

        public void ModelChange(object sender, ModelChangeEventArgs e)
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                this.MessageTextBlock.Text = e.Message;
            }));
            

            this.MessageTextBlock.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);           
        }


        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Controller.Instance.RegisterView(this);
        }


        private void Window_Closed(object sender, EventArgs e)
        {
            Controller.Instance.UnregisterView(this);            
            //Application.Current.Shutdown();
            //System.Diagnostics.Process.GetCurrentProcess().Kill();
        }

        #endregion      

       
        private void ButtonOpen_Click(object sender, RoutedEventArgs e)
        {
            OpenFile(); 
        }


        XmlCachingResolver resolver;
        Stopwatch stopWatch;        

        private void OpenFile()
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.FileName = String.Empty;

            Nullable<bool> result = ofd.ShowDialog();

            if (result == true)
            {
                ClearViews();

                this.tabControlMessages.SelectedIndex = 0;

                richTextBox1.Focus();

                fileName = ofd.FileName;

                UpdateListOfRecentFiles();

                resolver = new XmlCachingResolver(true);

                if (userSettings.Server.Length > 0)
                {
                    ICredentials myCred = new NetworkCredential(userSettings.UserName, userSettings.Password, userSettings.Domain);

                    try
                    {
                        resolver.ProxyServer = new WebProxy(userSettings.Server + ":" + userSettings.Port, true, new string[] { }, myCred);
                    }
                    catch (UriFormatException ex)
                    {
                        if (userSettings.Server.Length == 0)
                        {
                            MessageBox.Show("The proxy server must be configured");
                            return;
                        }

                        MessageBox.Show("Error on proxy: " + userSettings.Server + ":" + userSettings.Port + Environment.NewLine + ex.Message);
                        return;
                    }
                }

                stopWatch = Stopwatch.StartNew();                

                this.MessageTextBlock.Text = "DTS discovery...";
                this.MessageTextBlock.InvalidateVisual();

                backgroundWorkerOpenFile.RunWorkerAsync();
            }
        }


        private void ClearViews()
        {
            richTextBox1.Document.Blocks.Clear();             
            webBrowserMsg.Navigate("about:blank");
            webBrowserGraph.Navigate("about:blank");
            dgConcepts.ItemsSource = null;

            this.tabControlLinkbases.Items.Clear();
            this.tabControlDTS.Items.Clear();      
            //treeViewDts.Items.Clear();

            this.InvalidateVisual();
        }


        private void UpdateListOfRecentFiles()
        {
            List<string> recentFilesOld = userSettings.RecentlyOpenedFiles;

            if (!recentFilesOld.Contains(fileName))
            {
                recentFilesOld.Add(fileName);
            }

            if (recentFilesOld.Count == 11)
            {
                recentFilesOld.RemoveAt(0);
            }

            userSettings.RecentlyOpenedFiles = recentFilesOld;
            userSettings.Save();
        }


        private void backgroundWorkerOpenFile_DoWork(object sender, DoWorkEventArgs e)
        {
            XbrlDocument xbrlDocument = null;

            try
            {
                xbrlDocument = new XbrlDocument(null, fileName, "", "", resolver);                    

                if (xbrlDocument.DocType == "xbrl")
                {         
                    xbrlDoc = new InstanceDocument(xbrlDocument, resolver);                    
                    
                    ValidateInstance vi = new ValidateInstance(xbrlDoc as InstanceDocument);
                }
                else if (xbrlDocument.DocType == "schema")
                {
                    Action action = () => this.MessageTextBlock.Text = "Loading schema..." + xbrlDocument.FileName; 
                    MessageTextBlock.Dispatcher.Invoke(action);
                    
                    xbrlDoc = new TaxonomySchema(xbrlDocument, resolver);
                }
                else if (xbrlDocument.DocType == "linkbase")
                {
                    Action action = () => this.MessageTextBlock.Text = "Loading linkbase..." + xbrlDocument.FileName;
                    MessageTextBlock.Dispatcher.Invoke(action);

                    xbrlDoc = new LinkbaseDocument(xbrlDocument, resolver);
                }
                else
                {
                    Action action = () => this.MessageTextBlock.Text = "Loading xml document..." + xbrlDocument.FileName;
                    MessageTextBlock.Dispatcher.Invoke(action);

                    xbrlDoc = xbrlDocument;
                    
                    xbrlDoc.Dts = new DTS(xbrlDocument, resolver);
                    //ButtonValidateDTS.IsEnabled = true;
                    
                    ValidateXmlDoc();
                }

                Action action1 = () => this.MessageTextBlock.Text = "";
                this.MessageTextBlock.Dispatcher.Invoke(action1);
                Action action2 = () => this.MessageTextBlock.InvalidateVisual();
                this.MessageTextBlock.Dispatcher.Invoke(action2);                
            }
            catch (XmlException ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            catch (WebException ex)
            {
                MessageBox.Show("The proxy server must be configured\n" + ex.Message);
                return;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
        }


        private void backgroundWorkerOpenFile_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (xbrlDoc == null)
            {
                return;
            }

            this.Title = "Tapioca - " + xbrlDoc.FileName;

            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            richTextBox1.AppendText("Document loaded in " + ts.ToString(@"mm\:ss\.fff") + "\n");

            BuildViews();

            ButtonValidateDTS.IsEnabled = true;
            ButtonClose.IsEnabled = true;

            if (xbrlDoc.NamespaceManager.HasNamespace("us-gaap"))
            {
                renderingMenuItem.IsEnabled = true;
            }

        }


        # region Build Views

        private void BuildViews()
        {
            this.MessageTextBlock.Text = "Building Views...";
            this.MessageTextBlock.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);   

            Stopwatch stopWatch = Stopwatch.StartNew();

            CreateTreeViewDTS();

            CreateXmlEditor();

            CreateTreeViewLinkbases();

            ListAllConcepts();

            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;

            this.MessageTextBlock.Text = "";
            this.MessageTextBlock.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);  

            richTextBox1.AppendText("Build Views in " + ts.ToString(@"mm\:ss\.fff") + "\n");
            richTextBox1.ScrollToEnd();
        }        


        private void CreateTreeViewDTS()
        {
            TabItem TabItemDTS = new TabItem() { Header = "DTS" };

            this.treeViewDts = new TreeView();
            this.treeViewDts.HorizontalContentAlignment = HorizontalAlignment.Stretch;
            this.treeViewDts.VerticalContentAlignment = VerticalAlignment.Stretch;
            this.treeViewDts.BorderThickness = new Thickness(2);
            this.treeViewDts.Style = (Style)this.treeViewDts.FindResource("FontStyle");
            this.treeViewDts.Name = "treeViewDts";
            this.treeViewDts.Margin = new Thickness(0,0,0 ,0);
            this.treeViewDts.MouseDoubleClick += new System.Windows.Input.MouseButtonEventHandler(this.treeViewDts_MouseDoubleClick);
            TabItemDTS.Content = this.treeViewDts;
            this.tabControlDTS.Items.Add(TabItemDTS);
            this.tabControlDTS.SelectedIndex = 0;

            ContextMenu cm = this.FindResource("cmDTS") as ContextMenu;
            this.treeViewDts.ContextMenu = cm;

            TreeViewItem rootNode = new TreeViewItem() { Header = xbrlDoc.FileName };

            this.treeViewDts.Items.Add(rootNode);

            foreach (TaxonomySchema currentSchema in xbrlDoc.Dts.TaxonomySchemas)
            {
                if (xbrlDoc.DocType == "xbrl")
                {
                    if (currentSchema.ParentDocument != null && currentSchema.ParentDocument == xbrlDoc)
                    {
                        TreeViewItem schemaNode = new TreeViewItem() { Header = currentSchema.FileName, Foreground = Brushes.Black, Tag = currentSchema.PathFile };
                        rootNode.Items.Add(schemaNode);

                        schemaNode = GetExternalSchema(currentSchema.XmlSchema, schemaNode);

                        foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                        {
                            if (currentLinkbase.Schema != null && currentLinkbase.Schema == currentSchema.XmlSchema)
                            {
                                TreeViewItem linkbaseNode = new TreeViewItem() { Header = currentLinkbase.FileName + " - linkbase", Foreground = Brushes.Black, Tag = currentLinkbase.PathFile };
                                schemaNode.Items.Add(linkbaseNode);

                                linkbaseNode = GetSchemaFromLinkbase(currentLinkbase, linkbaseNode);
                            }
                        }
                    }
                }
                else if (xbrlDoc.DocType == "schema")
                {
                    if (currentSchema.ParentDocument == xbrlDoc)
                    {
                        TreeViewItem schemaNode = new TreeViewItem() { Header = currentSchema.FileName, Foreground = Brushes.Black, Tag = currentSchema.PathFile };
                        rootNode.Items.Add(schemaNode);
                    }

                    if (currentSchema.FileName == xbrlDoc.FileName)
                    {
                        rootNode = GetExternalSchema(currentSchema.XmlSchema, rootNode);

                        foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                        {
                            if (currentLinkbase.Schema != null && currentLinkbase.Schema == (xbrlDoc as TaxonomySchema).XmlSchema)
                            {
                                TreeViewItem linkbaseNode = new TreeViewItem() { Header = currentLinkbase.FileName + " - linkbase", Foreground = Brushes.Black, Tag = currentLinkbase.PathFile };
                                rootNode.Items.Add(linkbaseNode);

                                linkbaseNode = GetSchemaFromLinkbase(currentLinkbase, linkbaseNode);
                            }
                        }
                    }
                }
                else
                {
                    if (currentSchema.ParentDocument == xbrlDoc)
                    {
                        TreeViewItem schemaNode = new TreeViewItem() { Header = currentSchema.FileName, Foreground = Brushes.Black, Tag = currentSchema.PathFile };
                        rootNode.Items.Add(schemaNode);
                    }

                    rootNode = GetExternalSchema(currentSchema.XmlSchema, rootNode);                    
                }
            }

            AddLinkbaseNode(rootNode);
        }

        TabItem TabItemFile;
        bool dirty = false;

        private void CreateXmlEditor()
        {
            //TabItemFile.Visibility = Visibility.Visible;
            TabItemFile = new TabItem() { Header =  GetFileName(fileName) };
            textEditor = new TextEditor();
            textEditor.ShowLineNumbers = true;
            //textEditor.FontFamily = new FontFamily("Microsoft Sans Serif");
            //textEditor.FontSize = 12;
            this.textEditor.Style = (Style)this.textEditor.FindResource("FontStyle");
            ContextMenu cm = this.FindResource("cmAvalonEdit") as ContextMenu;
            textEditor.ContextMenu = cm;

            textEditor.Load(fileName);
            textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml");

            TabItemFile.Content = textEditor;
            this.tabControlLinkbases.Items.Add(TabItemFile);

            this.textEditor.GotFocus += new System.Windows.RoutedEventHandler(this.textEditor_GotFocus);
            this.textEditor.LostFocus += new System.Windows.RoutedEventHandler(this.textEditor_LostFocus);
            this.textEditor.TextChanged += new System.EventHandler(this.textEditor_TextChanged);
        }
      

        private void AddLinkbaseNode(TreeViewItem instanceNode)
        {
            foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
            {
                if (currentLinkbase.Instance != null && currentLinkbase.Instance == xbrlDoc)
                {
                    TreeViewItem linkbaseNode = new TreeViewItem() { Header = currentLinkbase.FileName + " - linkbase", Foreground = Brushes.Black, Tag = currentLinkbase.PathFile };
                    instanceNode.Items.Add(linkbaseNode);

                    linkbaseNode = GetSchemaFromLinkbase(currentLinkbase, linkbaseNode);
                }
            }
        }


        private TreeViewItem GetSchemaFromLinkbase(LinkbaseDocument linkbase, TreeViewItem linkbaseNode)
        {
            GetSchemaInXsiLocation(linkbase, linkbaseNode);

            //ArcRoleRef
            GetSchemaInArcRoleRef(linkbase, linkbaseNode);

            //RoleRef
            GetSchemaInRoleRef(linkbase, linkbaseNode);

            return linkbaseNode;
        }

        
        private void GetSchemaInArcRoleRef(LinkbaseDocument linkbase, TreeViewItem linkbaseNode)
        {
            IEnumerable<XElement> arcRolesRefNodes = from c in linkbase.ThisXDocument.Root.Elements()
                                                     where c.Name.LocalName.Equals("arcroleRef")
                                                     select c;

            foreach (XElement element in arcRolesRefNodes)
            {
                XNamespace ns = Constants.XLINK;
                string arcroleURI = (string)element.Attribute("arcroleURI") ?? string.Empty;
                XAttribute attrHref = element.Attribute(ns + "href");

                if (attrHref != null)
                {
                    HyperlinkReference xp = new HyperlinkReference(attrHref.Value);

                    if (!(xp.Url.Length == 0))
                    {
                        if (!ContainNodeName(linkbaseNode, xp))
                        {
                            TreeViewItem schemaNode = new TreeViewItem() { Header = GetFileName(xp.Url), Foreground = Brushes.Black, Tag = xp.Url };
                            linkbaseNode.Items.Add(schemaNode);

                            schemaNode = GetExternalSchema(GetSchemaFromLinkbase(xp.Url), schemaNode);
                        }
                    }
                }
            }
        }


        private void GetSchemaInRoleRef(LinkbaseDocument linkbase, TreeViewItem linkbaseNode)
        {
            IEnumerable<XElement> rolesRefNodes = from c in linkbase.ThisXDocument.Root.Elements()
                                                     where c.Name.LocalName.Equals("roleRef")
                                                     select c;

            foreach (XElement element in rolesRefNodes)
            {
                XNamespace ns = Constants.XLINK;
                string arcroleURI = (string)element.Attribute("aroleURI") ?? string.Empty;
                XAttribute attrHref = element.Attribute(ns + "href");

                if (attrHref != null)
                {
                    HyperlinkReference xp = new HyperlinkReference(attrHref.Value);

                    if (!(xp.Url.Length == 0))
                    {
                        if (!ContainNodeName(linkbaseNode, xp))
                        {
                            TreeViewItem schemaNode = new TreeViewItem() { Header = GetFileName(xp.Url), Foreground = Brushes.Black, Tag = xp.Url };
                            linkbaseNode.Items.Add(schemaNode);

                            schemaNode = GetExternalSchema(GetSchemaFromLinkbase(xp.Url), schemaNode);
                        }
                    }
                }
            }
        }


        private bool ContainNodeName(TreeViewItem linkbaseNode, HyperlinkReference xp)
        {
            foreach (TreeViewItem node in linkbaseNode.Items)
            {
                if (node.Name == xp.Url)
                {
                    return true;
                }
            }

            return false;
        }


        private void GetSchemaInXsiLocation(LinkbaseDocument linkbase, TreeViewItem linkbaseNode)
        {
            XNamespace xsi = Constants.XSI;
            string schemaLocation = (string)linkbase.ThisXDocument.Root.Attribute(xsi + "schemaLocation") ?? string.Empty;

            if (schemaLocation != null)
            {
                schemaLocation = schemaLocation.TrimEnd().TrimStart().Replace("  ", " ");
                schemaLocation = Regex.Replace(schemaLocation, @"\s+", " ");
                string[] schemaLocationSplit = schemaLocation.ToString().Split(' ');

                if (schemaLocationSplit.Length > 1)
                {
                    string Base = (string)linkbase.ThisXDocument.Root.Attribute("base") ?? string.Empty;
                    string baseUri = linkbase.ThisXDocument.Root.BaseUri;

                    for (int i = 0; i < schemaLocationSplit.Length; i = i + 2)
                    {
                        string fileName = schemaLocationSplit[i + 1];

                        TreeViewItem schemaNode = new TreeViewItem() { Header = GetFileName(fileName), Foreground = Brushes.Black, Tag = fileName };
                        linkbaseNode.Items.Add(schemaNode);

                        schemaNode = GetExternalSchema(GetSchemaFromLinkbase(fileName), schemaNode);
                    }
                }
            }
        }


        private string GetFileName(string href)
        {
            string nameFile = href;
            int LastPathSeparator = href.LastIndexOf('/');

            if (LastPathSeparator == -1)
            {
                LastPathSeparator = href.LastIndexOf('\\');

                if (LastPathSeparator != -1)
                {
                    nameFile = href.Substring(LastPathSeparator + 1);
                }
            }

            nameFile = href.Substring(LastPathSeparator + 1);

            return nameFile;
        }


        private XmlSchema GetSchemaFromLinkbase(string fileName)
        {
            foreach (TaxonomySchema currentSchema in xbrlDoc.Dts.TaxonomySchemas)
            {
                if (currentSchema.FileName == GetFileName(fileName))
                {
                    return currentSchema.XmlSchema;
                }

                foreach (XmlSchemaObject schema in currentSchema.XmlSchema.Includes)
                {
                    XmlSchema externalSchema = null;

                    if (schema is XmlSchemaImport)
                    {
                        externalSchema = ((XmlSchemaImport)schema).Schema;

                        if (externalSchema.SourceUri == fileName)
                        {
                            return externalSchema;
                        }
                    }
                }
            }

            return null;
        }


        private TreeViewItem GetExternalSchema(XmlSchema currentSchema, TreeViewItem schemaNode)
        {
            if (currentSchema == null)
            {
                return schemaNode;
            }

            foreach (XmlSchemaObject schema in currentSchema.Includes)
            {
                XmlSchema externalSchema = null;

                if (schema is XmlSchemaImport)
                {
                    externalSchema = ((XmlSchemaImport)schema).Schema;

                    string schemaImportName = System.IO.Path.GetFileName(externalSchema.SourceUri);

                    //TreeViewItem schemaImportNode = new TreeViewItem(schemaImportName);
                    TreeViewItem schemaImportNode = new TreeViewItem() { Header = schemaImportName, Foreground = Brushes.Black, Tag = externalSchema.SourceUri };
                    schemaNode.Items.Add(schemaImportNode);

                    schemaImportNode = GetExternalSchema(externalSchema, schemaImportNode);

                    foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                    {
                        if (currentLinkbase.Schema != null && currentLinkbase.Schema == externalSchema)
                        {
                            TreeViewItem linkbaseNode = new TreeViewItem() { Header = currentLinkbase.FileName + " - linkbase", Foreground = Brushes.Black, Tag = currentLinkbase.PathFile };
                            schemaImportNode.Items.Add(linkbaseNode);

                            linkbaseNode = GetSchemaFromLinkbase(currentLinkbase, linkbaseNode);
                        }
                    }
                }
            }

            return schemaNode;
        }


        private void ValidateXmlDoc()
        {
            ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationHandler);

            try
            {
                XmlSchemaSet xmlSchemaSet = new XmlSchemaSet();

                foreach (TaxonomySchema taxonomySchema in xbrlDoc.Dts.TaxonomySchemas)
                {
                    if (taxonomySchema.ParentDocument is InstanceDocument)
                    {
                        xmlSchemaSet.Add(taxonomySchema.XmlSchemaSet);
                    }
                }

                this.Dispatcher.Invoke((Action)(() =>
                {
                    richTextBox1.AppendText("Validating xml document: " + xbrlDoc.FileName + " targetNamespace:");                    
                }));

                xbrlDoc.ThisXDocument.Validate(xmlSchemaSet, eventHandler, true);
            }
            catch (XmlSchemaValidationException ex)
            {
                richTextBox1.AppendText("Validation error on ValidateInstance:" + ex.Message);
            }
        }


        private void ValidationHandler(object sender, ValidationEventArgs e)
        {
            richTextBox1.AppendText("Validation error on ValidateInstance, LineNumber:" + e.Exception.LineNumber + ":" + e.Exception.LinePosition);
        }


        private void CreateTreeViewLinkbases()
        {
            TabItem TabItemPresentation = null;
            TabItem TabItemDefinition = null;
            TabItem TabItemCalculation = null;

            ContextMenu cm = this.FindResource("contextMenu") as ContextMenu;

            foreach (NetworkGraph ng in xbrlDoc.Dts.NetworkGraphs)
            {
                // A presentation network
                if (ng.TupleNG.Item1.Equals("presentationLink"))
                {
                    if (TabItemPresentation == null)
                    {
                        //TabItemPresentation.Visibility = Visibility.Visible;
                        TabItemPresentation = new TabItem() { Header = "Presentation" };
                        this.tvPresentation = new TreeView();                       
                        this.tvPresentation.Style = (Style)this.tvPresentation.FindResource("FontStyle");
                        this.tvPresentation.HorizontalContentAlignment = HorizontalAlignment.Stretch;
                        this.tvPresentation.VerticalContentAlignment = VerticalAlignment.Stretch;
                        this.tvPresentation.Name = "tvPresentation";
                        TabItemPresentation.Content = this.tvPresentation;
                        this.tabControlLinkbases.Items.Add(TabItemPresentation);
                        this.tvPresentation.ContextMenu = cm;
                    }
                  
                }
                else if (ng.TupleNG.Item1.Equals("definitionLink"))
                {
                    if (TabItemDefinition == null)
                    {
                        //TabItemDefinition.Visibility = Visibility.Visible;
                        TabItemDefinition = new TabItem() { Header = "Definition" };
                        this.tvDefinition = new TreeView();                       
                        this.tvDefinition.Style = (Style)this.tvDefinition.FindResource("FontStyle");
                        this.tvDefinition.HorizontalContentAlignment = HorizontalAlignment.Stretch;
                        this.tvDefinition.VerticalContentAlignment = VerticalAlignment.Stretch;
                        this.tvDefinition.Name = "tvDefinition";
                        TabItemDefinition.Content = this.tvDefinition;
                        this.tabControlLinkbases.Items.Add(TabItemDefinition);
                        this.tvDefinition.ContextMenu = cm;
                    }
                }
                else if (ng.TupleNG.Item1.Equals("calculationLink"))
                {
                    if (TabItemCalculation == null)
                    {
                        this.ButtonCalculation.IsEnabled = true;

                        //TabItemCalculation.Visibility = Visibility.Visible;
                        TabItemCalculation = new TabItem() { Header = "Calculation" };
                        this.tvCalculation = new TreeView();                        
                        this.tvCalculation.Style = (Style)this.tvCalculation.FindResource("FontStyle");
                        this.tvCalculation.HorizontalContentAlignment = HorizontalAlignment.Stretch;
                        this.tvCalculation.VerticalContentAlignment = VerticalAlignment.Stretch;
                        this.tvCalculation.Name = "tvCalculation";
                        TabItemCalculation.Content = this.tvCalculation;
                        this.tabControlLinkbases.Items.Add(TabItemCalculation);
                        this.tvCalculation.ContextMenu = cm;
                    }
                }
                else
                {
                    if (!(ng.TupleNG.Item1.Equals("labelLink") && ng.TupleNG.Item1.Equals("referenceLink")) &&
                        !IsFormulaLinkbase())
                    {
                        TabItem TabItemGeneric = new TabItem() { Header = ng.TupleNG.Item1 };
                        this.tvGeneric = new TreeView();
                        this.tvGeneric.HorizontalContentAlignment = HorizontalAlignment.Stretch;
                        this.tvGeneric.VerticalContentAlignment = VerticalAlignment.Stretch;
                        this.tvGeneric.Name = "tv" + ng.TupleNG.Item1.Replace("Link", "");
                        this.tvGeneric.ContextMenu = cm;

                        TabItemGeneric.Content = this.tvGeneric;
                        this.tabControlLinkbases.Items.Add(TabItemGeneric);
                    }
                }
            }

            foreach (NetworkGraph ng in xbrlDoc.Dts.NetworkGraphs)
            {
                // A presentation network
                if (ng.TupleNG.Item1.Equals("presentationLink"))
                {
                    string definition = GetDefinitionOfRoleType(ng.TupleNG.Item2);

                    TreeViewItem presentationNode = null;

                    ContainsNode(tvPresentation, definition);

                    if (!ContainsNode(tvPresentation, definition))
                    {
                        presentationNode = new TreeViewItem() { Header = definition };
                        //presentationNode.Name = definition;
                        tvPresentation.Items.Add(presentationNode);
                    }
                    else
                    {
                        presentationNode = GetTreeViewItem(tvPresentation, definition);
                    }

                    TreeViewItem arcRoleNode = new TreeViewItem() { Header = ng.TupleNG.Item4 };
                    presentationNode.Items.Add(arcRoleNode);

                    foreach (Arc arc in ng.NetworkRelationships)
                    {
                        TreeViewItem arcNode = new TreeViewItem() { Header = arc.FromId + " --> " + arc.ToId };
                        arcRoleNode.Items.Add(arcNode);
                    }

                    (this.tvPresentation.Items[0] as TreeViewItem).IsSelected = true;
                }

                // A definition network
                else if (ng.TupleNG.Item1.Equals("definitionLink"))
                {
                    string definition = GetDefinitionOfRoleType(ng.TupleNG.Item2);

                    TreeViewItem definitionNode = null;

                    if (!ContainsNode(tvDefinition, definition))
                    {
                        definitionNode = new TreeViewItem() { Header = definition };
                        //definitionNode.Name = definition;
                        tvDefinition.Items.Add(definitionNode);
                    }
                    else
                    {
                        definitionNode = GetTreeViewItem(tvDefinition, definition);
                    }

                    TreeViewItem arcRoleNode = new TreeViewItem() { Header = ng.TupleNG.Item4 };
                    definitionNode.Items.Add(arcRoleNode);

                    foreach (Arc arc in ng.NetworkRelationships)
                    {
                        TreeViewItem arcNode = new TreeViewItem() { Header = arc.FromId + " --> " + arc.ToId };
                        arcRoleNode.Items.Add(arcNode);
                    }

                    (this.tvDefinition.Items[0] as TreeViewItem).IsSelected = true;
                }

                else if (ng.TupleNG.Item1.Equals("calculationLink"))
                {
                    string definition = GetDefinitionOfRoleType(ng.TupleNG.Item2);

                    TreeViewItem definitionNode = null;

                    if (!ContainsNode(tvCalculation, definition))
                    {
                        definitionNode = new TreeViewItem() { Header = definition };
                        //definitionNode.Name = definition;
                        tvCalculation.Items.Add(definitionNode);
                    }
                    else
                    {
                        definitionNode = GetTreeViewItem(tvCalculation, definition);
                    }

                    TreeViewItem arcRoleNode = new TreeViewItem() { Header = ng.TupleNG.Item4 };
                    definitionNode.Items.Add(arcRoleNode);

                    foreach (Summation summation in ng.SummationConcepts)
                    {
                        TreeViewItem summationNode = new TreeViewItem() { Header = summation.SummationLocator.Label };
                        arcRoleNode.Items.Add(summationNode);

                        foreach (Locator locator in summation.ContributingLocators)
                        {
                            TreeViewItem contributingNode = new TreeViewItem() { Header = locator.Label };
                            summationNode.Items.Add(contributingNode);
                        }
                    }

                    (this.tvCalculation.Items[0] as TreeViewItem).IsSelected = true;
                }
                else if (!ng.TupleNG.Item1.Equals("labelLink") && !ng.TupleNG.Item1.Equals("referenceLink") && !ng.TupleNG.Item1.Equals("link"))
                {
                    TreeViewItem roleNode = new TreeViewItem() { Header = ng.TupleNG.Item2 };
                    tvGeneric.Items.Add(roleNode);

                    foreach (Arc arc in ng.NetworkRelationships)
                    {
                        TreeViewItem arcNode = new TreeViewItem() { Header = arc.FromId + " to " + arc.ToId };
                        roleNode.Items.Add(arcNode);
                    }

                    (this.tvGeneric.Items[0] as TreeViewItem).IsSelected = true;
                }
            }


            if (IsFormulaLinkbase())
            {
                CreateTreeViewFormula();
            }

            if (IsDimensionalTaxonomy())
            {
                CreateTreeViewDimension();
            }

            this.tabControlLinkbases.SelectedIndex = 0;
        }


        private bool ContainsNode(TreeView treeView, string definition)
        {
            foreach (TreeViewItem node in treeView.Items)
            {
                if (node.Header.Equals(definition))
                {
                    return true;
                }
            }

            return false;
        }


        private TreeViewItem GetTreeViewItem(TreeView treeView, string definition)
        {
            foreach (TreeViewItem node in treeView.Items)
            {
                if (node.Header.Equals(definition))
                {
                    return node;
                }
            }

            return null;
        }


        private string GetDefinitionOfRoleType(string roleUri)
        {
            foreach (RoleType roleType in xbrlDoc.Dts.RoleTypes)
            {
                if (roleType.RoleUri.Equals(roleUri))
                {
                    if (roleType.Definition != null)
                    {
                        return roleType.Definition;
                    }
                    else
                    {
                        return roleUri;
                    }
                }
            }

            return roleUri;
        }


        private void CreateTreeViewFormula()
        {
            this.ButtonFormula.IsEnabled = true;
            //TabItemFormula.Visibility = Visibility.Visible;
            TabItem tabPageFormula = new TabItem() { Header = "Formula" };
            this.tvFormula = new TreeView();            
            this.tvFormula.Style = (Style)this.tvFormula.FindResource("FontStyle");
            this.tvFormula.HorizontalContentAlignment = HorizontalAlignment.Stretch;
            this.tvFormula.VerticalContentAlignment = VerticalAlignment.Stretch;
            this.tvFormula.Name = "tvFormula";
            tabPageFormula.Content = this.tvFormula;
            this.tabControlLinkbases.Items.Add(tabPageFormula);

            ContextMenu cm = this.FindResource("contextMenu") as ContextMenu;
            this.tvFormula.ContextMenu = cm;
            

            CreateAssertionsSet();

            // ValueAssertions

            CreateValueAssertions(this.tvFormula.Items, xbrlDoc.Dts.DtsFormula.ValueAssertions);

            // ExistenceAssertions

            CreateExistenceAssertions(this.tvFormula.Items, xbrlDoc.Dts.DtsFormula.ExistenceAssertions);

            // ConsistencyAssertions

            CreateConsistencyAssertions(this.tvFormula.Items, xbrlDoc.Dts.DtsFormula.ConsistencyAssertions);

            // Formulas

            CreateFormula();

            (this.tvFormula.Items[0] as TreeViewItem).IsSelected = true;
        }


        private void CreateAssertionsSet()
        {
            foreach (AssertionSet assertionSet in xbrlDoc.Dts.DtsFormula.AssertionSets)
            {
                TreeViewItem idNode = new TreeViewItem() { Header = "assertionSet " + assertionSet.Label };
                this.tvFormula.Items.Add(idNode);

                // ValueAssertions

                CreateValueAssertions(idNode.Items, assertionSet.ValueAssertions);

                // ExistenceAssertions

                CreateExistenceAssertions(idNode.Items, assertionSet.ExistenceAssertions);

                // ConsistencyAssertions

                CreateConsistencyAssertions(idNode.Items, assertionSet.ConsistencyAssertions);
            }
        }


        private void CreateValueAssertions(ItemCollection nodes, List<ValueAssertion> valueAssertions)
        {
            foreach (ValueAssertion assertion in valueAssertions)
            {
                TreeViewItem idNode = new TreeViewItem() { Header = "valueAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label) };
                nodes.Add(idNode);

                foreach (FactVariable factVariable in assertion.FactVariables)
                {
                    TreeViewItem factVariableNode = new TreeViewItem() { Header = "factVariable " + factVariable.Label};
                    idNode.Items.Add(factVariableNode);

                    foreach (Filter filter in factVariable.Filters)
                    {
                        TreeViewItem filterNode = new TreeViewItem() { Header="filter " + filter.ResourceName};
                        factVariableNode.Items.Add(filterNode);

                        if (filter.ResourceName.Equals("conceptName"))
                        {
                            foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                            {
                                TreeViewItem conceptNode = new TreeViewItem() { Header="concept " + conceptName};
                                filterNode.Items.Add(conceptNode);
                            }
                        }
                    }
                }

                if (assertion.MessageSatisfied != null)
                {
                    TreeViewItem MessageNode = new TreeViewItem(){ Header="message satisfied" + assertion.MessageSatisfied.Label + " " + assertion.MessageSatisfied.Content};
                    idNode.Items.Add(MessageNode);
                }

                if (assertion.MessageUnsatisfied != null)
                {
                    TreeViewItem MessageNode = new TreeViewItem(){ Header="message unsatisfied" + assertion.MessageUnsatisfied.Label + " " + assertion.MessageUnsatisfied.Content};
                    idNode.Items.Add(MessageNode);
                }
            }
        }


        private void CreateExistenceAssertions(ItemCollection nodes, List<ExistenceAssertion> existenceAssertions)
        {
            foreach (ExistenceAssertion assertion in existenceAssertions)
            {
                TreeViewItem idNode = new TreeViewItem() { Header = "existenceAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label) };
                nodes.Add(idNode);

                foreach (FactVariable factVariable in assertion.FactVariables)
                {
                    TreeViewItem factVariableNode = new TreeViewItem() { Header = "factVariable " + factVariable.Label };
                    idNode.Items.Add(factVariableNode);

                    foreach (Filter filter in factVariable.Filters)
                    {
                        TreeViewItem filterNode = new TreeViewItem() { Header = "filter " + filter.ResourceName };
                        factVariableNode.Items.Add(filterNode);

                        if (filter.ResourceName.Equals("conceptName"))
                        {
                            foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                            {
                                TreeViewItem conceptNode = new TreeViewItem() { Header = "concept " + conceptName };
                                filterNode.Items.Add(conceptNode);
                            }
                        }
                    }
                }

                if (assertion.MessageSatisfied != null)
                {
                    TreeViewItem MessageNode = new TreeViewItem() { Header = "message satisfied" + assertion.MessageSatisfied.Label + " " + assertion.MessageSatisfied.Content };
                    idNode.Items.Add(MessageNode);
                }

                if (assertion.MessageUnsatisfied != null)
                {
                    TreeViewItem MessageNode = new TreeViewItem() { Header = "message unsatisfied" + assertion.MessageUnsatisfied.Label + " " + assertion.MessageUnsatisfied.Content };
                    idNode.Items.Add(MessageNode);
                }
            }
        }


        private void CreateConsistencyAssertions(ItemCollection nodes, List<ConsistencyAssertion> consistencyAssertions)
        {
            foreach (ConsistencyAssertion assertion in consistencyAssertions)
            {
                TreeViewItem idNode = new TreeViewItem() { Header = "consistencyAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label) };
                nodes.Add(idNode);

                foreach (FormulaXBRL formula in assertion.FormulasXbrl)
                {
                    TreeViewItem formulaNode = new TreeViewItem() { Header = "formula " + (formula.Id != null ? formula.Id : formula.Label) };
                    idNode.Items.Add(formulaNode);

                    foreach (FactVariable factVariable in formula.FactVariables)
                    {
                        TreeViewItem factVariableNode = new TreeViewItem() { Header = "factVariable " + factVariable.Label };
                        formulaNode.Items.Add(factVariableNode);

                        foreach (Filter filter in factVariable.Filters)
                        {
                            TreeViewItem filterNode = new TreeViewItem() { Header = "filter " + filter.ResourceName };
                            factVariableNode.Items.Add(filterNode);

                            if (filter.ResourceName.Equals("conceptName"))
                            {
                                foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                                {
                                    TreeViewItem conceptNode = new TreeViewItem() { Header = "concept " + conceptName };
                                    filterNode.Items.Add(conceptNode);
                                }
                            }
                        }
                    }
                }

                if (assertion.MessageSatisfied != null)
                {
                    TreeViewItem MessageNode = new TreeViewItem() { Header = "message satisfied" + assertion.MessageSatisfied.Label + " " + assertion.MessageSatisfied.Content };
                    idNode.Items.Add(MessageNode);
                }

                if (assertion.MessageUnsatisfied != null)
                {
                    TreeViewItem MessageNode = new TreeViewItem() { Header = "message unsatisfied" + assertion.MessageUnsatisfied.Label + " " + assertion.MessageUnsatisfied.Content };
                    idNode.Items.Add(MessageNode);
                }
            }
        }


        private void CreateFormula()
        {
            foreach (FormulaXBRL formula in xbrlDoc.Dts.DtsFormula.Formulas)
            {
                TreeViewItem formulaNode = new TreeViewItem() { Header = "formula " + (formula.Id != null ? formula.Id : formula.Label) };
                this.tvFormula.Items.Add(formulaNode);

                foreach (FactVariable factVariable in formula.FactVariables)
                {
                    TreeViewItem factVariableNode = new TreeViewItem() { Header = "factVariable " + factVariable.Label };
                    formulaNode.Items.Add(factVariableNode);

                    foreach (Filter filter in factVariable.Filters)
                    {
                        TreeViewItem filterNode = new TreeViewItem() { Header = "filter " + filter.ResourceName };
                        factVariableNode.Items.Add(filterNode);

                        if (filter.ResourceName.Equals("conceptName"))
                        {
                            foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                            {
                                TreeViewItem conceptNode = new TreeViewItem() { Header = "concept " + conceptName };
                                filterNode.Items.Add(conceptNode);
                            }
                        }
                    }
                }
            }
        }


        private void CreateTreeViewDimension()
        {
            //TabItemDimension.Visibility = Visibility.Visible;
            TabItem tabPageDimension = new TabItem() { Header = "Dimension(DRS)" };
            this.tvDimension = new TreeView();            
            this.tvDimension.Style = (Style)this.tvDimension.FindResource("FontStyle");
            this.tvDimension.HorizontalContentAlignment = HorizontalAlignment.Stretch;
            this.tvDimension.VerticalContentAlignment = VerticalAlignment.Stretch;
            this.tvDimension.Name = "tvDimension";
            tabPageDimension.Content = this.tvDimension;
            this.tabControlLinkbases.Items.Add(tabPageDimension);

            ContextMenu cm = this.FindResource("contextMenu") as ContextMenu;
            this.tvDimension.ContextMenu = cm;

            foreach (DimensionalRelationshipSet drs in xbrlDoc.Dts.DtsDimension.DimensionalRelationshipSets)
            {
                string definition = GetDefinitionOfRoleType(drs.DRSRole);

                TreeViewItem drsRoleNode = null;

                if (!ContainsNode(tvDimension, definition))
                {
                    drsRoleNode = new TreeViewItem() { Header = definition };
                    drsRoleNode.Tag = definition;
                    tvDimension.Items.Add(drsRoleNode);
                }
                else
                {
                    drsRoleNode = GetTreeViewItem(tvDimension, definition);
                }

                //TreeViewItem arcRoleNode = new TreeViewItem(ng.TupleNG.Item4);
                //definitionNode.Nodes.Add(arcRoleNode);

                //TreeViewItem roleNode = new TreeViewItem(drs.DRSRole);
                //this.tvDimension.Nodes.Add(roleNode);

                foreach (ConsecutiveRelationshipsSet crs in drs.ConsecutiveRelationshipsSets)
                {
                    TreeViewItem primaryItemNode = new TreeViewItem() { Header = crs.HasHypercube.PrimaryItem.Name };
                    drsRoleNode.Items.Add(primaryItemNode);

                    TreeViewItem hypercubeNode = new TreeViewItem() { Header = crs.HasHypercube.Hypercube.Concept.Name + (crs.HasHypercube.TargetRole == null ? "" : " via TargetRole -> " + crs.HasHypercube.TargetRole.AbsoluteUri) };
                    primaryItemNode.Items.Add(hypercubeNode);

                    foreach (HypercubeDimension hypercubeDimension in crs.HypercubeDimensions)
                    {
                        TreeViewItem dimensionNode = new TreeViewItem() { Header = hypercubeDimension.Dimension.Concept.Name + (hypercubeDimension.TargetRole == null ? "" : " via TargetRole -> " + hypercubeDimension.TargetRole.AbsoluteUri) };
                        hypercubeNode.Items.Add(dimensionNode);

                        foreach (DimensionDomain dimensionDomain in crs.DimensionDomains)
                        {
                            if (dimensionDomain.Dimension == hypercubeDimension.Dimension)
                            {
                                TreeViewItem domainNode = new TreeViewItem() { Header = dimensionDomain.Domain.Concept.Name + (dimensionDomain.TargetRole == null ? "" : " via TargetRole -> " + dimensionDomain.TargetRole.AbsoluteUri) };
                                dimensionNode.Items.Add(domainNode);

                                foreach (DomainMember domainMember in crs.DomainMembers)
                                {
                                    if (dimensionDomain.Domain.Concept.Name.Equals(domainMember.Domain.Name))
                                    {
                                        TreeViewItem memberNode = new TreeViewItem() { Header = domainMember.Member.Name };
                                        domainNode.Items.Add(memberNode);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            (this.tvDimension.Items[0] as TreeViewItem).IsSelected = true;
        }


        private bool IsFormulaLinkbase()
        {
            foreach (LinkbaseDocument linkbase in xbrlDoc.Dts.LinkbaseDocuments)
            {
                if ((linkbase.NamespaceManager.HasNamespace("generic") || linkbase.NamespaceManager.HasNamespace("gen")
                    || linkbase.NamespaceManager.HasNamespace("xbrl-gen")) &&
                    linkbase.NamespaceManager.HasNamespace("variable"))
                {
                    return true;
                }
            }

            return false;
        }


        private bool HasLinkbase(string linkbase)
        {
            foreach (NetworkGraph ng in xbrlDoc.Dts.NetworkGraphs)
            {
                if (ng.TupleNG.Item1.Contains(linkbase))
                {
                    return true;
                }
            }

            return false;
        }


        private bool IsDimensionalTaxonomy()
        {
            foreach (NetworkGraph ng in xbrlDoc.Dts.NetworkGraphs)
            {
                if (ng.TupleNG.Item1.Contains("definition"))
                {
                    string dimensionalArcRoles = "http://xbrl.org/int/dim/arcrole/all" +
                                                 "http://xbrl.org/int/dim/arcrole/notAll" +
                                                 "http://xbrl.org/int/dim/arcrole/hypercube-dimension" +
                                                 "http://xbrl.org/int/dim/arcrole/dimension-domain" +
                                                 "http://xbrl.org/int/dim/arcrole/domain-member" +
                                                 "http://xbrl.org/int/dim/arcrole/dimension-default";

                    if (dimensionalArcRoles.Contains(ng.TupleNG.Item4))
                    {
                        return true;
                    }
                }
            }

            return false;
        }


        private void ListAllConcepts()
        {
            List<Concept> concepts = xbrlDoc.Dts.GetAllConcepts();

            DataTable table = new DataTable();
            //add in tables
            table.Columns.Add("Name", typeof(string));
            table.Columns.Add("Id", typeof(string));
            table.Columns.Add("Abstract", typeof(string));
            table.Columns.Add("Substitution Group", typeof(string));
            table.Columns.Add("Type", typeof(string));
            table.Columns.Add("Period Type", typeof(string));
            table.Columns.Add("Balance", typeof(string));

            foreach (Concept concept in concepts)
            {
                //add in rows
                table.Rows.Add(concept.Name, concept.Id, concept.SchemaElement.IsAbstract, concept.SchemaElement.SubstitutionGroup.Name,
                               concept.TypeName.Name, concept.PeriodTypeString, concept.BalanceString);
            }

            dgConcepts.AutoGenerateColumns = true;
            dgConcepts.ItemsSource = table.DefaultView;
        }


        #endregion


        # region Validate Taxonomy

        Stopwatch stopWatchDTS;

        private void ButtonValidateDTS_Click(object sender, RoutedEventArgs e)
        {
            this.tabControlMessages.SelectedIndex = 0;
            richTextBox1.Focus();
            richTextBox1.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);

            stopWatchDTS = Stopwatch.StartNew();

            backgroundWorkerValidateDTS.RunWorkerAsync();
        }


        private void backgroundWorkerValidateDTS_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            //this.Dispatcher.Invoke((Action)(() =>
            //{
            ValidateDts vDts = new ValidateDts(xbrlDoc.Dts);
            ValidateLinkbases vlb = new ValidateLinkbases(xbrlDoc.Dts);
            ValidateDimensionalTaxonomy vd = new ValidateDimensionalTaxonomy(xbrlDoc.Dts);
            ValidateLinkbaseFormula vlf = new ValidateLinkbaseFormula(xbrlDoc.Dts);
            //}));
        }


        private void backgroundWorkerValidateDTS_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.MessageTextBlock.Text = "";
            richTextBox1.Focus();
            richTextBox1.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);

            stopWatchDTS.Stop();
            TimeSpan ts = stopWatchDTS.Elapsed;

            richTextBox1.AppendText("\nProcessing time of DTS validation:" + ts.ToString(@"mm\:ss\.fff") + "\n");
            richTextBox1.ScrollToEnd();
        }


        private void ButtonCalculation_Click(object sender, RoutedEventArgs e)
        {
            this.tabControlMessages.SelectedIndex = 0;
            richTextBox1.Focus();
            richTextBox1.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);

            backgroundWorkerCalculation.RunWorkerAsync();
        }


        private void backgroundWorkerCalculation_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            //this.Dispatcher.Invoke((Action)(() =>
            //{
                ValidateCalculations vc = new ValidateCalculations(xbrlDoc.Dts, true);
            //}));
        }


        private void backgroundWorkerCalculation_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.MessageTextBlock.Text = "";
            this.MessageTextBlock.InvalidateVisual();

            //webBrowserMsg.Visibility = Visibility.Visible;
            webBrowserMsg.Navigate(new Uri(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/Tapioca/CalculationMessages.html"));
            tabControlMessages.SelectedItem = tabItemWebBrowser;
            //UpdateLayout();
            this.tabControlMessages.SelectedIndex = 2;
            webBrowserMsg.Focus();            
            webBrowserMsg.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
        }


        private void ButtonFormula_Click(object sender, RoutedEventArgs e)
        {
            //this.MessageTextBlock.Text = "Validating Formula...";
            //this.MessageTextBlock.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);

            this.tabControlMessages.SelectedIndex = 0;
            richTextBox1.Focus();
            richTextBox1.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);

            backgroundWorkerFormula.RunWorkerAsync();
        }


        private void backgroundWorkerFormula_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            FormulaProcessor vf = new FormulaProcessor(xbrlDoc.Dts, true);

        }


        private void backgroundWorkerFormula_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.MessageTextBlock.Text = "";
            this.MessageTextBlock.InvalidateVisual();

            //webBrowserMsg.Visibility = Visibility.Visible;
            //webBrowserMsg.Document.Encoding = "iso-8859-9";                         
            
            tabControlMessages.SelectedItem = tabItemWebBrowser;
            tabControlMessages.Focus();
            this.tabControlMessages.SelectedIndex = 2;
            tabItemWebBrowser.IsSelected = true;
            tabItemWebBrowser.Focus();
            tabControlMessages.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
            UpdateLayout();
            webBrowserMsg.Navigate(new Uri(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/Tapioca/FormulaMessages.html"));
            webBrowserMsg.Focus();            
            webBrowserMsg.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
            //this.MessageTextBlock.Text = "Finished formual. tabControl:" + this.tabControlMessages.SelectedIndex;
        }

        #endregion


        private void MenuItemClear_Click(object sender, RoutedEventArgs e)
        {
            richTextBox1.Document.Blocks.Clear();
        }


        private void MenuItemCopy_Click(object sender, RoutedEventArgs e)
        {
            Clipboard.SetText(new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd).Text);
        }


        SaveFileDialog saveFileDialog1;

        private void MenuItemFile_Click(object sender, RoutedEventArgs e)
        {
            saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.FileOk += new System.ComponentModel.CancelEventHandler(saveFileDialog1_FileOk);
            saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            saveFileDialog1.DefaultExt = "txt";
            saveFileDialog1.Title = "Save a File";
            saveFileDialog1.ShowDialog();    
        }


        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            // Get file name.
            string name = saveFileDialog1.FileName;
            // Write to the file name selected.
            System.IO.File.WriteAllText(name, new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd).Text);
        }


        private void proxyServerMenuItem_Click(object sender, RoutedEventArgs e)
        {
            ProxySetting window = new ProxySetting();

            window.Domain = userSettings.Domain;
            window.Server = userSettings.Server;
            window.Port = userSettings.Port;
            window.Username = userSettings.UserName;
            window.Password = userSettings.Password;

            if (!(bool) window.ShowDialog())
            {
                return;
            }

            userSettings.Domain = window.Domain;
            userSettings.Server = window.Server;
            userSettings.Port = window.Port;
            userSettings.UserName = window.Username;
            userSettings.Password = window.Password;
            userSettings.Save(); 
        }


        private void closeMenuItem_Click(object sender, RoutedEventArgs e)
        {
            ButtonValidateDTS.IsEnabled = false;
            ButtonCalculation.IsEnabled = false;
            ButtonFormula.IsEnabled = false;

            ClearViews();
        }


        private void ButtonClose_Click(object sender, RoutedEventArgs e)
        {
            ButtonValidateDTS.IsEnabled = false;
            ButtonCalculation.IsEnabled = false;
            ButtonFormula.IsEnabled = false;
            ButtonClose.IsEnabled = true;

            ClearViews();
        }


        private void treeView_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            TreeViewItem ClickedTreeViewItem = new TreeViewItem();

            //find the original object that raised the event
            UIElement ClickedItem = VisualTreeHelper.GetParent(e.OriginalSource as UIElement) as UIElement;

            //find the clicked TreeViewItem
            while ((ClickedItem != null) && !(ClickedItem is TreeViewItem))
            {
                ClickedItem = VisualTreeHelper.GetParent(ClickedItem) as UIElement;
            }

            ClickedTreeViewItem = ClickedItem as TreeViewItem;
            ClickedTreeViewItem.IsSelected = true;
            ClickedTreeViewItem.Focus();
        }


        # region Generate Graph Diagram

        private void GenerateGraphDiagram(string linkbase, TreeViewItem selected)
        {
            new DiagramGraphs().CreateDotFile(selected.Header.ToString(), linkbase, xbrlDoc, ref pathToDotFile);

            GenDiagramFile();
        }


        private void GenerateGraphDiagramFormula(TreeViewItem selected)
        {
            DiagramGraphs.CreateFormulaDotFile(selected.Header.ToString(), xbrlDoc, ref pathToDotFile);

            GenDiagramFile();
        }
        

        private void GenDiagramFile()
        {
            progressWindow.Show();

            backgroundWorkerGenDiagram.RunWorkerAsync();
        }


        private void backgroundWorkerGenDiagram_DoWork(object sender, DoWorkEventArgs e)
        {
            string fileType = userSettings.FileType;
            string engine = userSettings.LayoutEngine;

            diagramFile = pathToDotFile.Replace(".dot", "." + fileType);

            if (File.Exists(diagramFile))
            {
                File.Delete(diagramFile);
            }

            //MessageBox.Show(Environment.CurrentDirectory + @"\dot\dot" +" " + pathToDotFile + " -o " + diagramFile + " -T" + fileType + " -K" + engine + " -Goverlap=prism");

            ExecuteCommand(Environment.CurrentDirectory + @"\dot\dot", string.Format(@"""{0}"" -o ""{1}"" -T"
                           + fileType + " -K" + engine + " -Goverlap=prism", pathToDotFile, diagramFile));

            FileInfo f = new FileInfo(diagramFile);

            if (f.Length == 0)
            {
                ExecuteCommand(Environment.CurrentDirectory + @"\dot\dot", string.Format(@"""{0}"" -o ""{1}"" -Tpng -Ksfdp -Goverlap=prism",
                               pathToDotFile, diagramFile));
            }
        }


        private void backgroundWorkerGenDiagram_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressWindow.Hide();

            tabControlMessages.SelectedItem = tabItemGraphDiagram;
            //tabItemGraphDiagram.IsSelected = true;
            webBrowserGraph.Focus();

            webBrowserGraph.Navigate(diagramFile);
            //webBrowserGraph.Navigate(diagramFile + "?zoom=400%&navpanes=0&toolbar=0");
        }

        private static void ExecuteCommand(string command, string @params)
        {
            Process proc = new Process();
            proc.StartInfo = new ProcessStartInfo(command, @params) { CreateNoWindow = true, UseShellExecute = false };

            proc.Start();
            proc.WaitForExit();
        }

        #endregion


        private void aboutMenuItem_Click(object sender, RoutedEventArgs e)
        {
            Window dialog = new AboutBox();          
            dialog.ShowDialog();
        }


        private void generateGraphMenuItem_Click(object sender, RoutedEventArgs e)
        {
            string linkbase = "";

            MenuItem menuItem = sender as MenuItem;

            ContextMenu contextMenu = (sender as MenuItem).Parent as ContextMenu;

            if (contextMenu != null)
            {
                // Get the control that is displaying this context menu
                Control sourceControl = contextMenu.PlacementTarget as TreeView;
                //sourceControl.sel
                linkbase = FirstCharacterToLower(sourceControl.Name.Replace("tv", ""));
            }

            if (linkbase == "formula")
            {
                GenerateGraphDiagramFormula(tvFormula.SelectedItem as TreeViewItem);
                return;
            }
            else if (linkbase == "definition")
            {
                GenerateGraphDiagram(linkbase, tvDefinition.SelectedItem as TreeViewItem);
                return;
            }
            else if (linkbase == "presentation")
            {
                GenerateGraphDiagram(linkbase, tvPresentation.SelectedItem as TreeViewItem);
                return;
            }
            else if (linkbase == "calculation")
            {
                GenerateGraphDiagram(linkbase, tvCalculation.SelectedItem as TreeViewItem);
                return;
            }
            else if (linkbase == "dimension")
            {
                GenerateGraphDiagram(linkbase, tvDimension.SelectedItem as TreeViewItem);
                return;
            }
            //GenerateGraphDiagram(linkbase);
            GenerateGraphDiagram(linkbase, tvDefinition.SelectedItem as TreeViewItem);
        }


        public static string FirstCharacterToLower(string str)
        {
            if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
                return str;

            return Char.ToLowerInvariant(str[0]).ToString() + str.Substring(1);
        }


        private void viewlinkbaseFileMenuItem_Click(object sender, RoutedEventArgs e)
        {
            string linkbaseName = "";

            MenuItem menuItem = sender as MenuItem;

            if (menuItem != null)
            {
                ContextMenu contextMenu = menuItem.ContextMenu;

                if (contextMenu != null)
                {
                    // Get the control that is displaying this context menu
                    Control sourceControl = contextMenu.PlacementTarget as TreeView;
                    linkbaseName = sourceControl.Name.Replace("tv", "").ToLower();
                }
            }

            if (linkbaseName == "formula")
            {
                foreach (LinkbaseDocument linkbase in xbrlDoc.Dts.LinkbaseDocuments)
                {
                    if ((linkbase.NamespaceManager.HasNamespace("generic") || linkbase.NamespaceManager.HasNamespace("gen")
                        || linkbase.NamespaceManager.HasNamespace("xbrl-gen")) &&
                        linkbase.NamespaceManager.HasNamespace("variable"))
                    {
                        webBrowserMsg.Navigate(linkbase.PathFile);
                        break;
                    }
                }
            }

            foreach (LinkbaseDocument linkbase in xbrlDoc.Dts.LinkbaseDocuments)
            {
                if (linkbase.RoleLinkbaseRef.Contains(linkbaseName))
                {
                    webBrowserMsg.Navigate(linkbase.PathFile);
                    break;
                }
            }

            tabControlMessages.SelectedItem = tabItemWebBrowser;
            webBrowserMsg.Focus();
        }


        private void expandAllMenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;

            ContextMenu contextMenu = (sender as MenuItem).Parent as ContextMenu;

            if (contextMenu != null)
            {
                // Get the control that is displaying this context menu
                TreeView sourceControl = contextMenu.PlacementTarget as TreeView;
                ExpandAllNodes(sourceControl.Items);
            }

        }


        private void ButtonSave_Click(object sender, RoutedEventArgs e)
        {
            textEditor.Save(fileName);
            dirty = false;
            TabItemFile.Header = TabItemFile.Header.ToString().Replace("*","");
        }


        private void ButtonFind_Click(object sender, RoutedEventArgs e)
        {
            FindAndReplaceWindow dialogFind = new FindAndReplaceWindow();
            dialogFind.Owner = this;
            dialogFind.ShowDialog();
        }


        private TreeViewItem m_OldSelectNode;

        private void treeViewDts_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            // Point where the mouse is clicked.
            Point p = e.GetPosition(this);

            // Get the node that the user has clicked.
            TreeViewItem treeViewItem = treeViewDts.SelectedItem as TreeViewItem;

            if (treeViewItem != null)
            {

                // Select the node the user has clicked.
                // The node appears selected until the menu is displayed on the screen.
                m_OldSelectNode = treeViewDts.SelectedItem as TreeViewItem;
                treeViewItem.IsSelected = true;

                string fileName = treeViewItem.Header.ToString().Replace(" - linkbase", "");

                webBrowserMsg.Navigate(treeViewItem.Tag.ToString());

                tabControlMessages.SelectedItem = tabItemWebBrowser;
                webBrowserMsg.Focus();
                //webBrowser.Refresh();

                // Highlight the selected node.
                m_OldSelectNode.IsSelected = true; ;
                m_OldSelectNode = null;
            }
        }


        private void recentFile1MenuItem_Click(object sender, EventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;

            if (menuItem != null)
            {
                ClearViews();

                this.tabControlMessages.SelectedIndex = 0;
                richTextBox1.Focus();

                OpenRecentFile(menuItem.Header.ToString());
            }
        }


        private void OpenRecentFile(string recentFileName)
        {
            resolver = new XmlCachingResolver(true);

            if (userSettings.Server.Length > 0)
            {
                string domain = "BCDF001";

                ICredentials myCred = new NetworkCredential(userSettings.UserName, userSettings.Password, domain);

                try
                {
                    resolver.ProxyServer = new WebProxy(userSettings.Server + ":" + userSettings.Port, true, new string[] { }, myCred);
                }
                catch (UriFormatException ex)
                {
                    if (userSettings.Server.Length == 0)
                    {
                        MessageBox.Show("The proxy server must be configured");
                    }

                    MessageBox.Show("Error on proxy: " + userSettings.Server + ":" + userSettings.Port + Environment.NewLine + ex.Message);
                }
            }

            stopWatch = Stopwatch.StartNew();

            richTextBox1.Focus();

            fileName = recentFileName;

            ButtonValidateDTS.IsEnabled = true;
            ButtonClose.IsEnabled = true;

            this.MessageTextBlock.Text = "DTS discovery...";
            this.MessageTextBlock.InvalidateVisual();

            backgroundWorkerOpenFile.RunWorkerAsync();
        }


        private void MenuItemCopyDTS_Click(object sender, RoutedEventArgs e)
        {
            Clipboard.SetText(AppendNode(treeViewDts.Items));
        }


        private string AppendNode(ItemCollection nodes)
        {
            StringBuilder sb = new StringBuilder();

            foreach (TreeViewItem node in nodes)
            {
                sb.AppendLine(node.Header.ToString());

                sb.AppendLine("\t" + AppendNode(node.Items));
            }

            return sb.ToString();
        }


        private void MenuItemExpandAll_Click(object sender, RoutedEventArgs e)
        {
            ExpandAllNodes(treeViewDts.Items);
        }


        private void ExpandAllNodes(ItemCollection items)
        {
            foreach (object item in items)
            {
                TreeViewItem treeItem = (TreeViewItem)item;

                if (treeItem != null)
                {
                    ExpandAllNodes(treeItem.Items);
                    treeItem.IsExpanded = true;
                }
            }
        }                       


        private void settingsMenuItem_Click(object sender, RoutedEventArgs e)
        {
            AppSetting window = new AppSetting();

            if (!(bool)window.ShowDialog())
            {
                return;
            }           

            userSettings.LayoutEngine = window.Engine;
            userSettings.FileType = window.FileType;
            userSettings.Save(); 
        }


        private void MenuItemGenerateGraph_Click(object sender, RoutedEventArgs e)
        {
            DTS dts = xbrlDoc.Dts;

            if (File.Exists("DTSGraph.dot"))
            {
                File.Delete("DTSGraph.dot");
            }

            pathToDotFile = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Tapioca\\DTSGraph.dot";

            DiagramGraphs.CreateDTSDotFile(xbrlDoc);

            GenDiagramFile();
        }


        private void OpenFile(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFile();
        }


        private void SaveAsFile(object sender, ExecutedRoutedEventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".txt";

            if (dlg.ShowDialog() ?? false)
            {
                fileName = dlg.FileName;
            }
            else
            {
                return;
            }

            textEditor.Save(fileName);

            dirty = false;
            TabItemFile.Header = TabItemFile.Header.ToString().Replace("*", "");
        }


        private void CopyToClipboardMenuItem_Click(object sender, RoutedEventArgs e)
        {
            Clipboard.SetText(textEditor.Text);
        }


        private void textEditor_DocumentChanged(object sender, EventArgs e)
        {
            TabItemFile.Header = TabItemFile.Header + "*";
        }


        private void textEditor_GotFocus(object sender, RoutedEventArgs e)
        {
            ButtonFind.IsEnabled = true;
        }


        private void textEditor_LostFocus(object sender, RoutedEventArgs e)
        {
            ButtonFind.IsEnabled = false;
        }


        private void textEditor_TextChanged(object sender, EventArgs e)
        {
            if (!dirty)
            {
                TabItemFile.Header = TabItemFile.Header + "*";
            }

            dirty = true;
        }


        public static RoutedCommand MyCommand = new RoutedCommand();

        private void AddHotKeys()
        {
            try
            {
                MyCommand.InputGestures.Add(new KeyGesture(Key.T, ModifierKeys.Control));

                RoutedCommand firstSettings = new RoutedCommand();
                firstSettings.InputGestures.Add(new KeyGesture(Key.F, ModifierKeys.Control));
                CommandBindings.Add(new CommandBinding(firstSettings, ButtonFind_Click));

                RoutedCommand secondSettings = new RoutedCommand();
                secondSettings.InputGestures.Add(new KeyGesture(Key.B, ModifierKeys.Alt));
                CommandBindings.Add(new CommandBinding(secondSettings, MyCommandExecuted));
            }
            catch (Exception)
            {
                //handle exception error
            }
        }


        private void MyCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            //handler code goes here.
            MessageBox.Show("Alt+B key pressed");
        }


        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            ReportModel reportModel = new ReportModel();
            reportModel.XbrlDoc = xbrlDoc;
            reportModel.Show();
            reportModel.InitializeRendering(resolver);
        }


       
       
    }
}
